﻿#include "../../thirdparty/klogger/klogger/interface/logger.h"
#include "../../thirdparty/klogger/klogger/interface/logger_factory.h"

#include "../box/timer_factory.hh"
#include "../console/console_impl.hh"
#include "../detail/box_argument_impl.hh"
#include "../detail/box_config_impl.hh"
#include "../detail/command_manager.hh"
#include "../detail/debug_server_impl.hh"
#include "../detail/interface_descriptor_impl.hh"
#include "../detail/lang_impl.hh"
#include "../detail/memory_allocator_impl.hh"
#include "../detail/proc_stat_impl.hh"
#include "../detail/proxy_handler_impl.hh"
#include "../detail/rpc_logger_impl.hh"
#include "../detail/scope_curl.hh"
#include "../detail/service_context_impl.hh"
#include "../detail/service_layer.hh"
#include "../detail/sys_logger_impl.hh"

#include "../repo/src/include/root/rpc_logger.h"
#include "../repo/src/include/root/rpc_proxy.h"
#include "../repo/src/include/root/rpc_root.h"
#include "../repo/src/include/root/rpc_stub.h"

#include "../service_finder/service_finder.hh"
#include "../service_register/service_register.hh"

#include "../util/os_util.hh"
#include "../util/string_util.hh"
#include "../util/time_system.hh"
#include "../util/time_util.hh"

#include "box_channel.hh"
#include "box_network.hh"
#include "box_os.hh"
#include "fixed_mem_pool.hh"
#include "local_command.hh"
#include "service_box.hh"
#include "service_http_loader.hh"

#include <chrono>
#include <fstream>
#include <iostream>
#include <list>
#include <string>
#include <vector>

#ifdef WIN32
#include "../detail/os_service_windows.hh"
#include "../detail/stack_trace_windows.hh"
#else
#include "../detail/stack_trace_linux.hh"
#endif // WIN32

namespace kratos {
namespace service {

static rpc::TransportPtr NullTransport;

/**
 * 分配内存, 用于RPC框架内部的内存分配, 接管RPC内存分配到服务器容器的内存池
 *
 * \param size 长度
 * \return 地址
 */
static auto rpc_malloc(std::size_t size) -> void * {
  return reinterpret_cast<void *>(box_malloc(size));
}

/**
 * 释放内存, 用于RPC框架内部的内存释放
 *
 * \param p 地址
 * \return
 */
static auto rpc_free(void *p) -> void { box_free(p); }

ServiceBox::ServiceBox() {}

ServiceBox::~ServiceBox() {}

auto ServiceBox::start(int argc, const char **argv) -> bool {
  try {
    // 启动
    auto result = start_internal(argc, argv);
    if (!result) {
      if (is_client()) {
        return false;
      }
      // 启动失败
      write_log(lang::LangID::LANG_BOX_START_FAILURE, klogger::Logger::FATAL);
    }
    return result;
  } catch (std::exception &e) {
    // 启动时发生异常
    write_log(lang::LangID::LANG_STARTUP_EXCEPTION, klogger::Logger::FATAL,
              e.what());
  }
  return false;
}

auto ServiceBox::start_internal(int argc, const char **argv) -> bool {
  // 日志语言包，后续预置日志输出可以多国语言化
  lang_ = kratos::make_unique_pool_ptr<lang::LangImpl>();
  // 解析命令行
  if (!parse_command_line(argc, argv)) {
    return false;
  }
  // 解析配置文件
  if (!parse_config_file()) {
    return false;
  }
  // 执行命令
  if (is_client()) {
    // 执行命令
    do_command();
    // 命令发送完毕后退出
    return false;
  }
  // 开启syslog
  start_syslog();
#ifndef WIN32
  // 检查是否以daemon方式启动
  check_daemon();
#endif // WIN32
  if (box_argument_->is_open_system_exception()) {
    // 转换系统异常为C++异常
    util::StackTrace::install_system_exception(this);
  }
  // 初始化服务容器
  if (!initialize()) {
    return false;
  }
  // 等待获取必需的服务, 必须在最后调用，防止循环等待
  wait_necessary_service();
  // 打印启动信息
  print_startup_info();
  // 尝试开启时间系统
  time_system::TimeSystem::open_time_system(this);
  return true;
}

auto ServiceBox::update_internal(std::time_t now) -> void {
  // 设置最近一次TICK的时间戳
  util::set_last_timestamp_millionsecond(now);
  if (!now) {
    // 如果没有传入有效时间戳，则从系统获取
    now = util::get_os_time_millionsecond();
  }
  if (time_system::TimeSystem::is_open_time_system()) {
    // 如果开启时间系统则调用主循环
    time_system::TimeSystem::update(now);
  }
  // 网络循环
  BoxNetwork::update();
  // RPC框架主循环
  if (rpc_) {
    rpc_->update(now);
  }
  // 远程仓库更新主循环
  if (http_loader_) {
    http_loader_->update();
  }
  // 远程命令框架主循环
  if (command_manager_) {
    command_manager_->update(now);
  }
  // 内存管理主循环
  MempoolRef.update(now);
  // 代理主循环
  if (proxy_handler_) {
    proxy_handler_->update(now);
  }
  // 服务发现相关
  if (service_finder_) {
    service_finder_->update(now);
  }
  if (service_register_) {
    service_register_->update(now);
  }
  // 控制台
  if (console_) {
    console_->update();
  }
  // 脚本调试器
  if (debug_server_) {
    debug_server_->update();
  }
}

auto ServiceBox::update_unsafe(std::time_t now) -> void {
#ifdef WIN32
  if (box_argument_->is_open_system_exception()) {
    // SEH异常转换为C++异常
    // 这里必须使用结构化异常的方式才能将系统异常转化为
    // 使用try-catch捕获的异常
    __try {
      update_internal(now);
    } __finally {
    }
  } else {
    update_internal(now);
  }
#else
  update_internal(now);
#endif // WIN32
}

auto ServiceBox::stop_unsafe() -> bool {
  write_log(lang::LangID::LANG_BOX_START_CLEANUP, klogger::Logger::INFORMATION);
  // 卸载所有服务
  release_all_service();
  // 关闭调试器
  if (debug_server_) {
    debug_server_->stop();
  }
  // 反注册所有服务
  // 防止内部遍历删除registered_service_map_
  auto temp_map = registered_service_map_;
  for (const auto &it : temp_map) {
    unregister_service(it.first);
  }
  // 关闭HTTP组件
  if (http_loader_) {
    http_loader_->stop();
  }
  // 关闭服务注册/发现组件
  if (service_finder_) {
    service_finder_->stop();
  }
  if (service_register_) {
    service_register_->stop();
  }
  // 关闭进程统计
  if (proc_stat_) {
    proc_stat_->stop();
  }
  // 关闭console
  if (console_) {
    console_->stop();
  }
  // 关闭网络
  BoxNetwork::stop();
  // 将堆快照写入日志
  if (box_argument_->is_dump_heap()) {
    auto &allocator =
        dynamic_cast<MemoryAllocatorImpl &>(service_context_->get_allocator());
    allocator.dump(klogger::Logger::WARNING, get_logger_appender());
  }
  // 释放RPC实例相关资源
  if (rpc_) {
    rpc_->deinitialize();
  }
  // 卸载所有已加载的bundle
  unload_all_bundle();
  if (box_config_) {
    // 卸载操作系统相关注册
    uninstall_os_things(box_config_->get_box_name());
    if (box_config_->is_start_as_daemon()) {
      daemon_finalize(box_config_->get_box_name());
    }
  }
  // 输出最后一条日志
  write_log(lang::LangID::LANG_BOX_STOPPED, klogger::Logger::INFORMATION);
  // 关闭日志
  close_logger_appender();
  return true;
}

auto ServiceBox::stop_internal() -> bool {
#ifdef WIN32
  if (box_argument_->is_open_system_exception()) {
    // SEH异常转换为C++异常
    // 这里必须使用结构化异常的方式才能将系统异常转化为
    // 使用try-catch捕获的异常
    bool result = false;
    __try {
      result = stop_unsafe();
    } __finally {
      return result;
    }
  } else {
    return stop_unsafe();
  }
#else
  return stop_unsafe();
#endif // WIN32
}

auto ServiceBox::load_config() -> bool {
  // 建立配置实例
  box_config_ = kratos::make_unique_pool_ptr<config::BoxConfigImpl>(this);
  try {
    // 返回的错误信息
    std::string error;
    // 加载配置
    if (!box_config_->load(config_file_path_, error)) {
      write_log(lang::LangID::LANG_BOX_PARSE_CONFIG_FAIL,
                klogger::Logger::FATAL, error.c_str());
      return false;
    }
  } catch (std::exception &ex) {
    // 配置读取错误
    write_log(lang::LangID::LANG_BOX_PARSE_CONFIG_FAIL, klogger::Logger::FATAL,
              ex.what());
    return false;
  }
  return true;
}

auto ServiceBox::stop() -> bool {
  try {
    return stop_internal();
  } catch (std::exception &e) {
    // 捕获所有非预期的异常
    write_log(lang::LangID::LANG_RUNTIME_EXCEPTION, klogger::Logger::FAILURE,
              typeid(e).name(), e.what());
  }
  // 如果开启了异常转换则卸载
  if (box_argument_->is_open_system_exception()) {
    util::StackTrace::uninstall_system_exception();
  }
  return false;
}

auto ServiceBox::update(std::time_t now) -> void {
  try {
    update_unsafe(now);
  } catch (std::exception &e) {
    // 捕获所有非预期的异常
    write_log(lang::LangID::LANG_RUNTIME_EXCEPTION, klogger::Logger::FAILURE,
              typeid(e).name(), e.what());
  }
}

auto ServiceBox::is_installed(const std::string &uuid) -> bool {
  return (installed_service_uuids_.find(uuid) !=
          installed_service_uuids_.end());
}

auto ServiceBox::check_daemon() -> void {
  // 命令行参数的配置可以覆盖配置文件配置
  // 命令行如果使用--daemon参数启动，不论配置文件中是否配置了service.is_start_as_daemon
  // = "true" 服务容器都会以daemon的方式启动
  if ((box_argument_->is_daemon() || box_config_->is_start_as_daemon())) {
    daemonize(box_argument_->get_config_file_name());
  }
}

auto ServiceBox::start_console_logger() -> bool {
  auto *logger = LoggerFactory::createLogger();
  if (!logger) {
    write_log(lang::LangID::LANG_BOX_CREATE_LOGGER_FAIL,
              klogger::Logger::FATAL);
    return false;
  }
  logger_ = logger;
  // 默认的终端日志，在用户日志建立起来以前，所有的错误信息都通过默认终端日志输出
  // TODO syslog
  try {
    console_appender_ =
        logger_->newAppender("default", CONSOLE_LOGGER_CONFIG_LINE);
  } catch (std::exception &ex) {
    write_log(lang::LangID::LANG_BOX_START_LOGGER_FAIL, klogger::Logger::FATAL,
              CONSOLE_LOGGER_CONFIG_LINE, ex.what());
    return false;
  }
  if (!console_appender_) {
    return false;
  }
  return true;
}

auto ServiceBox::start_standard_logger(const std::string &logger_config_line)
    -> bool {
  try {
    // 启动标准日志输出, 这个日志是标准日志添加器
    // 标准日志添加器是用户配置的日志
    user_appender_ = logger_->newAppender("stardard", logger_config_line);
  } catch (std::exception &ex) {
    write_log(lang::LangID::LANG_BOX_START_LOGGER_FAIL, klogger::Logger::FATAL,
              logger_config_line.c_str(), ex.what());
    return false;
  }
  if (!user_appender_) {
    // 用户日志建立失败
    return false;
  }
  return true;
}

auto ServiceBox::load_service(const std::string uuid,
                              const std::string &file_path) -> bool {
  if (!box_config_->get_service_finder_hosts().empty()) {
    // 如果配置了服务发现则把服务进行注册
    // 注册/uuid,ip:port
    if (!register_service(uuid)) {
      return false;
    }
    // TODO 这里需要一个日志输出，帮助配置遗失
  }
  return rpc::loadClass(rpc_.get(), uuid, file_path, false,
                        service_context_.get());
}

auto ServiceBox::load_all_service(const std::string &service_dir) -> bool {
  if (!util::is_path_exists(service_dir)) {
    // 本地服务目录不存在
    write_log(lang::LangID::LANG_BOX_LOCAL_SERVICE_DIR_NOT_FOUND,
              klogger::Logger::FATAL, service_dir.c_str());
    return false;
  }
  // 启动远程加载器
  http_loader_ = kratos::make_unique_pool_ptr<ServiceHttpLoader>();
  if (!http_loader_->start(this)) {
    if (!util::is_path_exists(service_dir)) {
      write_log(lang::LangID::LANG_BOX_START_REMOTE_SERVICE_FAIL,
                klogger::Logger::FAILURE);
      return false;
    }
  }
  // 预加载服务，只有预加载服务才会被服务容器运行
  for (const auto &it : box_config_->get_preload_service()) {
    auto full_path = util::complete_path(service_dir, it.second);
    if (!util::is_path_exists(full_path)) {
      write_log(lang::LangID::LANG_BOX_LOAD_LOCAL_SERVICE_DIR_NOT_FOUND,
                klogger::Logger::FAILURE, it.second.c_str(),
                service_dir.c_str(), it.first.c_str());
      continue;
    }
    if (!load_service(it.first, full_path)) {
      write_log(lang::LangID::LANG_BOX_LOAD_LOCAL_SERVICE_FAIL,
                klogger::Logger::FAILURE, it.second.c_str(),
                service_dir.c_str(), it.first.c_str());
      // 服务加载失败，跳过失败的服务，继续加载后续服务
      continue;
    } else {
      // 加载成功，输出信息
      write_log(lang::LangID::LANG_BOX_LOAD_LOCAL_SERVICE_SUCCESS,
                klogger::Logger::INFORMATION, full_path.c_str());
      installed_service_uuids_.emplace(it.first);
    }
  }
  return true;
}

auto ServiceBox::release_all_service() -> bool {
  if (!box_config_ || !rpc_) {
    return true;
  }
  // 卸载所有已加载的服务
  for (const auto &it : box_config_->get_preload_service()) {
    rpc::destroyServiceUnsafe(rpc_.get(), it.first);
  }
  return true;
}

auto ServiceBox::unload_all_bundle() -> bool {
  if (!box_config_ || !rpc_) {
    return true;
  }
  // 卸载所有已加载的服务
  for (const auto &it : box_config_->get_preload_service()) {
    rpc::unloadClassUnsafe(rpc_.get(), it.first);
  }
  return true;
}

auto ServiceBox::get_service_register() -> ServiceRegister * {
  return service_register_.get();
}

auto ServiceBox::get_register_services() -> const StringMap & {
  return registered_service_map_;
}

auto ServiceBox::get_sys_logger() -> SysLogger * { return sys_logger_.get(); }

auto ServiceBox::get_proxy_handler() -> rpc::ProxyHandlerImpl * {
  return proxy_handler_.get();
}

auto ServiceBox::get_logger_appender() -> klogger::Appender * {
  if (user_appender_) {
    return user_appender_;
  } else if (console_appender_) {
    return console_appender_;
  }
  return nullptr;
}

auto ServiceBox::get_lang() -> lang::Lang * { return lang_.get(); }

auto ServiceBox::get_command_manager() -> CommandManager * {
  return command_manager_.get();
}

auto ServiceBox::get_proc_stat() -> ProcStat * { return proc_stat_.get(); }

auto ServiceBox::start_all_listener() -> bool {
  // 启动所有本地网络监听器, 默认容器被连接的监听器
  for (const auto &addr : box_config_->get_listener_list()) {
    if (!start_listener(addr, "local")) {
      // 启动监听器失败
      return false;
    }
  }
  return true;
}

auto ServiceBox::start_listener(const std::string &host,
                                const std::string &name) -> bool {
  std::string ip;
  int port = 0;
  if (!util::get_host_config(host, ip, port)) {
    // 配置格式错误
    write_log(lang::LangID::LANG_BOX_START_LISTENER_FAIL,
              klogger::Logger::FATAL, host.c_str());
    return false;
  }
  if (!BoxNetwork::listen_at(name + "@" + host, ip, port)) {
    // 开启监听器失败
    write_log(lang::LangID::LANG_BOX_START_LISTENER_FAIL,
              klogger::Logger::FATAL, host.c_str());
    return false;
  }
  return true;
}

auto ServiceBox::start_proxy_listener() -> bool {
  if (!box_argument_->is_proxy()) {
    // 非代理模式
    return true;
  }
  proxy_handler_ = kratos::make_unique_pool_ptr<rpc::ProxyHandlerImpl>(this);
  if (box_config_->has_attribute("proxy.listener")) {
    auto hosts = box_config_->get_array<std::string>("proxy.listener");
    for (const auto &host : hosts) {
      if (!start_listener(host, "proxy")) {
        write_log(lang::LangID::LANG_BOX_START_LISTENER_FAIL,
                  klogger::Logger::FATAL, host.c_str());
        return false;
      }
    }
  } else {
    write_log(lang::LangID::LANG_PROXY_CONFIG_NOT_FOUND,
              klogger::Logger::FATAL);
    return false;
  }
  if (box_config_->has_attribute("proxy.seed")) {
    // GlobalIndex种子，保证不同代理产生的GlobalIndex不会重复
    auto seed = box_config_->get_number<std::uint8_t>("proxy.seed");
    proxy_handler_->set_seed(seed);
  } else {
    write_log(lang::LangID::LANG_PROXY_SEED_NOT_FOUND, klogger::Logger::FATAL);
    return false;
  }
  write_log(lang::LangID::LANG_START_AS_PROXY, klogger::Logger::WARNING);
  auto hosts = box_config_->get_array<std::string>("proxy.listener");
  for (const auto &host : hosts) {
    write_log(kratos::lang::LangID::LANG_PROXY_LISTENER_INFO,
              klogger::Logger::INFORMATION, host.c_str());
  }
  return true;
}

auto ServiceBox::connect_to_proxy() -> bool {
  if (box_argument_->get_proxy_host().empty()) {
    // 不连接到代理
    return true;
  }
  std::string ip;
  int port = 0;
  if (!util::get_host_config(box_argument_->get_proxy_host(), ip, port)) {
    // 获取代理地址失败
    return false;
  }
  // 连接到代理
  return BoxNetwork::connect_to("remote_proxy", ip, port, 5000);
}

auto ServiceBox::do_command() -> void {
  LocalCommand command(this);
  command.do_command(box_argument_->get_command());
}

auto ServiceBox::register_config_reload_listener() -> void {
  box_config_->add_reload_listener(
      "box", [&](const std::string &, const config::BoxConfig &new_config) {
        // 监听器变化，支持新增和修改，但已经启动的监听会保留
        on_listener_change(new_config);
        // 监听日志配置变化
        on_logger_config_line_change(new_config);
      });
}

auto ServiceBox::on_listener_change(const config::BoxConfig &new_config)
    -> void {
  const auto &old_listener = box_config_->get_listener_list();
  for (const auto listener : new_config.get_listener_list()) {
    if (old_listener.end() ==
        std::find(old_listener.begin(), old_listener.end(), listener)) {
      start_listener(listener, "local");
      write_log(lang::LangID::LANG_RELOAD_INFO, klogger::Logger::WARNING,
                "N/A.", listener.c_str());
    }
  }
}

auto ServiceBox::on_logger_config_line_change(
    const config::BoxConfig &new_config) -> void {
  if (box_config_->get_logger_config_line() !=
      new_config.get_logger_config_line()) {
    if (user_appender_) {
      user_appender_->reload(new_config.get_logger_config_line());
      write_log(lang::LangID::LANG_RELOAD_INFO, klogger::Logger::WARNING,
                box_config_->get_logger_config_line().c_str(),
                new_config.get_logger_config_line().c_str());
    }
  }
}

auto ServiceBox::is_client() -> bool {
  return (util::get_binary_name() == "box_client");
}

auto ServiceBox::parse_command_line(int argc, const char **argv) -> bool {
  box_argument_ = kratos::make_unique_pool_ptr<argument::BoxArgumentImpl>();
  if (!box_argument_->parse(argc, argv)) {
    if (box_argument_->is_print_help()) {
      std::cerr << box_argument_->get_help_string() << std::endl;
    } else {
      write_log(lang::LangID::LANG_BOX_PARSE_ARGUMENT_FAIL,
                klogger::Logger::FATAL);
      std::cerr << box_argument_->get_help_string() << std::endl;
    }
    return false;
  }
  return true;
}

auto ServiceBox::parse_config_file() -> bool { // 启动默认日志
  // 启动默认日志添加器
  if (!start_console_logger()) {
    return false;
  }
  // 如果启动时设置了--config-center则下载配置文件
  if (!try_download_from_config_center()) {
    return false;
  }
  // 加载配置
  config_file_path_ = box_argument_->get_config_file_path();
  if (!load_config()) {
    write_log(lang::LangID::LANG_BOX_LOAD_CONFIG_FAIL, klogger::Logger::FATAL,
              config_file_path_.c_str());
    return false;
  } else {
    // 设置配置重载监听
    register_config_reload_listener();
  }
  return true;
}

auto ServiceBox::initialize() -> bool {
  // 启动用户日志
  if (!start_standard_logger(box_config_->get_logger_config_line())) {
    return false;
  }
  // 初始化服务发现
  if (!initialize_service_finder()) {
    return false;
  }
  service_layer_ = kratos::make_unique_pool_ptr<ServicelLayer>(this);
  // 设置用户上线文
  service_context_ = make_unique_pool_ptr<ServiceContextImpl>(this);
  // 输出Logo
  write_log_line(klogger::Logger::INFORMATION,
                 std::string("\n") + argument::BoxArgumentImpl::get_logo());
  // 建立外部命令处理器
  command_manager_ = kratos::make_unique_pool_ptr<CommandManager>(this);
  // 启动外部命令处理器
  if (!command_manager_->start()) {
    return false;
  }
  // 启动console
  console_ = kratos::make_unique_pool_ptr<console::ConsoleImpl>(this);
  if (!console_->start()) {
    return false;
  }
  // 启动本地命令处理
  if (command_manager_->is_enable()) {
    local_command_ = kratos::make_unique_pool_ptr<LocalCommand>(this);
    if (!local_command_->start()) {
      return false;
    }
  }
  // 设置RPC日志
  rpc_logger_ = kratos::make_unique_pool_ptr<RpcLoggerImpl>(this);
  // 进程信息统计
  proc_stat_ = kratos::make_unique_pool_ptr<ProcStatImpl>();
  proc_stat_->start(this);
  // 启动网络
  if (!BoxNetwork::start()) {
    write_log(lang::LangID::LANG_BOX_START_NETWORK_FAIL,
              klogger::Logger::FATAL);
    return false;
  }
  // 启动本地监听
  if (!start_all_listener()) {
    return false;
  }
  // 建立RPC实例
  rpc_ = kratos::make_unique_pool_ptr<rpc::RpcImpl>();
  // 设置RPC内存分配器
  rpc_->setAllocator(rpc_malloc, rpc_free);
  // 建立接口描述工厂
  descriptor_factory_ =
      kratos::make_unique_pool_ptr<InterfaceDescriptorFactoryImpl>();
  // 设置接口描述工厂
  rpc_->setDescriptorFactory(descriptor_factory_.get());
  // 启动RPC
  rpc_->initialize(rpc_logger_.get(), box_config_->is_open_coroutine(),
                   box_config_->is_open_rpc_stat());
  // 设置定时器工厂
  rpc_timer_factory_ = kratos::make_unique_pool_ptr<TimerFactoryImpl>(this);
  setTimerFactory(rpc_timer_factory_.get());
  // 设置上下文，用户层将取这个指针进行交互
  rpc_->setContext(reinterpret_cast<void *>(
      dynamic_cast<ServiceContext *>(service_context_.get())));
  // 安装操作系统相关
  if (!install_os_things(box_config_->get_box_name(), this)) {
    write_log(lang::LangID::LANG_BOX_OS_REGISTER_FAIL, klogger::Logger::FATAL);
    return false;
  }
  // 启动脚本调试器
  if (!try_start_debugger_server()) {
    return false;
  }
  // 加载本地服务
  if (!load_all_service(box_config_->get_service_dir())) {
    return false;
  }
  if (!start_proxy_listener()) {
    // 如果配置了代理模式将已代理模式启动
    return false;
  }
  if (!connect_to_proxy()) {
    // 连接到代理
    return false;
  }
  return true;
}

auto ServiceBox::try_download_from_config_center() -> bool {
  if (box_argument_->get_config_center_api_url().empty()) {
    // 没有配置远程配置中心
    return true;
  }
  ScopeCurl curl;
  if (!curl.perform(box_argument_->get_config_center_api_url())) {
    // 下载远程配置失败
    return false;
  }
  std::fstream fs;
  fs.open(kratos::argument::BoxArgument::DEFAULT_CONFIG_FILE_NAME,
          std::ios::out | std::ios::trunc);
  if (!fs) {
    return false;
  }
  // 将下载的远程配置写入本地，默认的配置文件内
  curl.to_stream(fs);
  fs.close();
  return true;
}

auto ServiceBox::close_logger_appender() -> void {
  if (console_appender_) {
    console_appender_->destroy();
  }
  // 关闭用户日志添加器
  if (user_appender_) {
    user_appender_->destroy();
  }
  user_appender_ = nullptr;
  console_appender_ = nullptr;
  // 最后关闭日志
  if (logger_) {
    logger_->destroy();
  }
  logger_ = nullptr;
}

auto ServiceBox::start_syslog() -> bool {
#ifdef WIN32
  if (is_windows_service()) {
    sys_logger_ = kratos::make_unique_pool_ptr<SysLoggerImpl>(
        box_config_->get_box_name());
  }
#else
  if (box_config_->is_start_as_daemon()) {
    sys_logger_.reset(new SysLoggerImpl(box_config_->get_box_name()));
  }
#endif // WIN32
  return true;
}

auto ServiceBox::try_get_transport(const std::string &name)
    -> std::shared_ptr<rpc::Transport> {
  if (!box_argument_->get_proxy_host().empty() && proxy_transport_) {
    return proxy_transport_;
  }
  auto channel_id = service_layer_->get_channel(name);
  if (!channel_id) {
    return NullTransport;
  } else {
    return get_channel(channel_id);
  }
}

auto ServiceBox::get_transport_sync(const std::string &name,
                                    std::time_t timeout)
    -> std::shared_ptr<rpc::Transport> {
  if (!box_argument_->get_proxy_host().empty()) {
    auto start = util::get_os_time_millionsecond();
    while (!proxy_transport_) {
      update(util::get_os_time_millionsecond());
      std::this_thread::sleep_for(std::chrono::milliseconds(1));
      if (util::get_os_time_millionsecond() - start >= timeout) {
        return NullTransport;
      }
    }
    return proxy_transport_;
  }
  auto trans = try_get_transport(name);
  if (trans) {
    return trans;
  }
  // 以下操作将阻塞执行线程, 但不会阻塞逻辑主循环
  // 1. 连接到远程容器
  // 2. 获取服务管道
  auto start = util::get_os_time_millionsecond();
  std::uint64_t channel_id = 0;
  while (true) {
    // 从缓存内查找服务对应的管道
    channel_id = service_layer_->try_get_channel(name);
    if (channel_id) {
      break;
    }
    // 网络循环
    BoxNetwork::update();
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
    if (util::get_os_time_millionsecond() - start >= timeout) {
      return NullTransport;
    }
  }
  if (!channel_id) {
    return NullTransport;
  }
  return get_channel(channel_id);
}

auto ServiceBox::get_argument() const -> const argument::BoxArgument & {
  return *dynamic_cast<argument::BoxArgument *>(box_argument_.get());
}

auto ServiceBox::is_wait_stop() const -> bool { return is_wait_stop_; }

auto ServiceBox::write_log_line(int log_level, const std::string &log_line)
    -> void {
  if (user_appender_) {
    user_appender_->write(log_level, "%s", log_line.c_str());
  } else if (console_appender_) {
    console_appender_->write(log_level, "%s", log_line.c_str());
  }
}

auto ServiceBox::set_wait_stop_flag() -> void { is_wait_stop_ = true; }

auto ServiceBox::random_get_listener_host() -> std::string {
  const auto &local_listener = box_config_->get_listener_list();
  if (local_listener.empty()) {
    return "";
  }
  auto index =
      util::get_random_uint32(0, (std::uint32_t)local_listener.size() - 1);
  if (index >= local_listener.size()) {
    return "";
  }
  return local_listener[index];
}

auto ServiceBox::try_start_debugger_server() -> bool {
  if (box_config_->has_attribute("debugger.enable")) {
    if (!(box_config_->get_string("debugger.enable") == "true")) {
      // 未开启
      write_log_line(klogger::Logger::INFORMATION,
                     "Start script debugger disable");
      return true;
    }
  }
  if (!box_config_->has_attribute("debugger.listen")) {
    return false;
  }
  auto host = box_config_->get_string("debugger.listen");
  std::string ip;
  int port;
  if (!util::get_host_config(host, ip, port)) {
    return false;
  }
  debug_server_ = make_unique_pool_ptr<DebugServerImpl>(this);
  write_log_line(klogger::Logger::INFORMATION,
                 "Start script debugger@" + ip + ":" + std::to_string(port));
  return debug_server_->start(ip, port);
}

auto ServiceBox::get_rpc() -> rpc::Rpc * { return rpc_.get(); }

auto ServiceBox::get_console() -> kratos::console::ConsoleImpl * {
  return console_.get();
}

auto ServiceBox::get_service_finder() -> ServiceFinder * {
  return service_finder_.get();
}

auto ServiceBox::get_service_layer() -> ServicelLayer * {
  return service_layer_.get();
}

auto ServiceBox::get_service_updater() -> ServiceHttpLoader * {
  return http_loader_.get();
}

auto ServiceBox::get_debug_server() -> DebugServerImpl * {
  if (!debug_server_) {
    return nullptr;
  }
  return debug_server_.get();
}

auto ServiceBox::register_service(const std::string &name) -> bool {
  auto host = random_get_listener_host();
  if (host.empty()) {
    return false;
  }
  // 从listener.host内随机一个监听端口
  if (!service_register_->register_service(name, host)) {
    return false;
  }
  registered_service_map_[name] = host;
  write_log(lang::LangID::LANG_STARTUP_INFO_REGISTER_SERVICE,
            klogger::Logger::INFORMATION, name.c_str(), host.c_str());
  return true;
}

auto ServiceBox::unregister_service(const std::string &name) -> bool {
  auto it = registered_service_map_.find(name);
  if (it == registered_service_map_.end()) {
    return false;
  }
  auto retval = service_register_->unregister_service(name, it->second);
  if (retval) {
    write_log(lang::LangID::LANG_STARTUP_INFO_UNREGISTER_SERVICE,
              klogger::Logger::INFORMATION, name.c_str());
  }
  registered_service_map_.erase(it);
  return retval;
}

auto ServiceBox::get_config() -> kratos::config::BoxConfig & {
  return *box_config_.get();
}

auto ServiceBox::get_context() -> ServiceContext * {
  return service_context_.get();
}

void ServiceBox::on_listen(const std::string &name, bool success,
                           std::shared_ptr<BoxChannel> &) {
  if (!success) {
    write_log(lang::LangID::LANG_START_LISTENER_FAIL, klogger::Logger::FAILURE,
              name.c_str());
  }
}

void ServiceBox::on_accept(std::shared_ptr<BoxChannel> &channel) {
  if (channel->get_channel_name().find("proxy") != std::string::npos) {
    if (proxy_handler_) {
      // 其他容器主动连接了proxy端口
      proxy_handler_->on_accept(channel);
    }
  }
}

void ServiceBox::on_connect(const std::string &name, bool success,
                            std::shared_ptr<BoxChannel> &channel) {
  if (!success) {
    return;
  }
  if (name == "remote_proxy") {
    // 主动连接到了proxy
    proxy_transport_ = channel;
  } else {
    service_layer_->on_connect(name, channel->get_id());
  }
}

void ServiceBox::on_close(std::shared_ptr<BoxChannel> &channel) {
  if (channel->getGlobalIndex() != rpc::INVALID_GLOBAL_INDEX) {
    if (proxy_handler_) {
      proxy_handler_->on_close(channel);
    }
  } else {
    if (!channel->get_channel_name().empty()) {
      service_layer_->on_close(channel->get_channel_name(), channel->get_id());
    }
  }
}

void ServiceBox::on_data(std::shared_ptr<BoxChannel> &channel) {
  rpc::TransportPtr trans = channel;
  if (proxy_handler_) {
    rpc_->onMessage(trans, service_context_.get(), proxy_handler_.get());
  } else {
    rpc_->onMessage(trans, service_context_.get());
  }
}

auto ServiceBox::wait_necessary_service() -> void {
  write_log(lang::LangID::LANG_BOX_GETTING_NECESSARY_SERVICE,
            klogger::Logger::INFORMATION);
  const auto &name_list = box_config_->get_necessary_service();
  // 以下操作将阻塞执行线程, 但不会阻塞逻辑主循环
  // 服务启动必须依赖的服务被发现前会一直尝试获取直到获取完毕
  for (const auto &name : name_list) {
    write_log(lang::LangID::LANG_STARTUP_INFO_NECESSARY_SERVICE,
              klogger::Logger::INFORMATION, name.c_str());
    while (!get_transport_sync(name, 10)) {
      // 持续运行主循环，框架内事件可以被正常处理
      update(util::get_os_time_millionsecond());
    }
  }
  write_log(lang::LangID::LANG_BOX_GOT_NECESSARY_SERVICE,
            klogger::Logger::INFORMATION);
}

auto ServiceBox::initialize_service_finder() -> bool {
  const auto &finder_type = box_config_->get_service_finder_type();
  auto finder_connect_timeout =
      box_config_->get_service_finder_connect_timeout();
  const auto &finder_hosts = box_config_->get_service_finder_hosts();
  // 获取服务注册/发现
  service_register_ = getRegister(finder_type);
  service_finder_ = getFinder(finder_type);
  if (!service_register_ || !service_finder_) {
    write_log(lang::LangID::LANG_BOX_CREATE_FINDER_FAIL, klogger::Logger::FATAL,
              finder_type.c_str());
    return false;
  }
  if (!finder_hosts.empty()) {
    // 启动注册器
    if (!service_register_->start(finder_hosts, (int)finder_connect_timeout)) {
      write_log(lang::LangID::LANG_BOX_START_FINDER_FAIL,
                klogger::Logger::FATAL, finder_type.c_str(),
                finder_hosts.c_str());
      return false;
    }
    // 启动服务发现
    if (!service_finder_->start(finder_hosts, (int)finder_connect_timeout)) {
      write_log(lang::LangID::LANG_BOX_START_FINDER_FAIL,
                klogger::Logger::FATAL, finder_type.c_str(),
                finder_hosts.c_str());
      return false;
    }
  } else {
    // 未配置
  }
  return true;
}

auto ServiceBox::print_startup_info() -> void {
  using namespace kratos::lang;
  using namespace klogger;

  auto &config = get_config();
  // 打印核心配置的信息
  for (const auto &listener : config.get_listener_list()) {
    write_log(LangID::LANG_STARTUP_INFO_LISTENER, Logger::INFORMATION,
              listener.c_str());
  }
  write_log(LangID::LANG_STARTUP_INFO_FINDER, Logger::INFORMATION,
            config.get_service_finder_type().c_str(),
            config.get_service_finder_hosts().c_str());
  write_log(LangID::LANG_STARTUP_INFO_COROUTINE, Logger::INFORMATION,
            config.is_open_coroutine() ? "yes" : "no");
  write_log(lang::LangID::LANG_STARTUP_INFO_LOCAL_SERVICE_DIR,
            klogger::Logger::INFORMATION,
            get_config().get_service_dir().c_str());
  for (const auto &[_, name] : get_config().get_preload_service()) {
    write_log(lang::LangID::LANG_STARTUP_INFO_LOCAL_SERVICE,
              klogger::Logger::INFORMATION, name.c_str());
  }
  write_log(lang::LangID::LANG_STARTUP_INFO_OPEN_REMOTE_UPDATE,
            klogger::Logger::INFORMATION,
            get_config().is_open_remote_update() ? "yes" : "no");
  write_log(lang::LangID::LANG_STARTUP_INFO_REMOTE_REPO_DIR,
            klogger::Logger::INFORMATION,
            get_config().get_remote_service_repo_dir().empty()
                ? "N/A."
                : get_config().get_remote_service_repo_dir().c_str());
  write_log(lang::LangID::LANG_STARTUP_INFO_REMOTE_VERSION_API,
            klogger::Logger::INFORMATION,
            get_config().get_remote_service_repo_version_api().empty()
                ? "N/A."
                : get_config().get_remote_service_repo_version_api().c_str());
  write_log(
      lang::LangID::LANG_STARTUP_INFO_REMOTE_LATEST_VRSION_API,
      klogger::Logger::INFORMATION,
      get_config().get_remote_service_repo_latest_version_api().empty()
          ? "N/A."
          : get_config().get_remote_service_repo_latest_version_api().c_str());
  write_log(lang::LangID::LANG_STARTUP_INFO_REMOTE_UPDATE_CHECK_INTVAL,
            klogger::Logger::INFORMATION,
            get_config().get_remote_repo_check_interval());
  write_log(lang::LangID::LANG_STARTUP_INFO_DAEMON,
            klogger::Logger::INFORMATION,
            get_config().is_start_as_daemon() ? "yes" : "no");
  // 打印启动日志
  write_log(lang::LangID::LANG_BOX_STARTED, klogger::Logger::INFORMATION);
}

} // namespace service
} // namespace kratos
